package components.generator;

import java.util.ArrayList;
import java.util.List;

import com.uqbar.vainilla.DeltaState;
import com.uqbar.vainilla.GameComponent;
import components.asteroids.Asteroid;
import components.asteroids.AsteroidLvl1;
import components.asteroids.AsteroidLvl2;
import components.asteroids.AsteroidLvl3;
import components.scenes.MainGameScene;

public class AsteroidsGenerator extends GameComponent<MainGameScene> {

	
	private MainGameScene scene;
	
	private int currentLevel;
	


	private double asteroidTimeCounter;
	private double asteroidSpawnTime;
	
	private double levelTimeCounter;
	private double timeForNextLevel;
	
	private List<Asteroid >currentSpawningAsteroids;
	private List<Class<? extends Asteroid>> asteroidPool;
	
	public AsteroidsGenerator(MainGameScene aScene){
		this.setX(0);
		this.setY(0);
		this.scene = aScene;
		
		this.currentSpawningAsteroids = new ArrayList<Asteroid>();
		this.asteroidTimeCounter = 0;
		this.levelTimeCounter = 0;
		
		this.currentLevel = 0;
		
		this.asteroidSpawnTime = 8;
		this.timeForNextLevel = 12;
		
	}
	public int getCurrentLevel() {
		return currentLevel;
	}


	public void setCurrentLevel(int currentLevel) {
		this.currentLevel = currentLevel;
	}

	
	public double getAsteroidTimeCounter() {
		return asteroidTimeCounter;
	}


	public void setAsteroidTimeCounter(double asteroidTimeCounter) {
		this.asteroidTimeCounter = asteroidTimeCounter;
	}


	public double getAsteroidSpawnTime() {
		return asteroidSpawnTime;
	}


	public void setAsteroidSpawnTime(double asteroidSpawnTime) {
		this.asteroidSpawnTime = asteroidSpawnTime;
	}


	public double getLevelTimeCounter() {
		return levelTimeCounter;
	}


	public void setLevelTimeCounter(double levelTimeCounter) {
		this.levelTimeCounter = levelTimeCounter;
	}


	public double getTimeForNextLevel() {
		return timeForNextLevel;
	}


	public void setTimeForNextLevel(double timeForNextLevel) {
		this.timeForNextLevel = timeForNextLevel;
	}


	public List<Class<? extends Asteroid>> getAsteroidPool() {
		return asteroidPool;
	}


	public void setAsteroidPool(List<Class<? extends Asteroid>> asteroidPool) {
		this.asteroidPool = asteroidPool;
	}
	
	
	public void update(DeltaState delta){
		this.increaseAsteroidCounter(delta.getDelta());
		this.increaseLevelTime(delta.getDelta());
		
		if (this.getAsteroidTimeCounter() > this.getAsteroidSpawnTime()){
			this.resetAsteroidCounter();
			this.addAsteroids();
		}
		if(this.getLevelTimeCounter() > this.getTimeForNextLevel()){
			this.resetLevelTimeCounter();
			this.nextLevel();
		}
	}


	private void nextLevel() {
		//this.getCurrentSpawningAsteroids().add(this.getAsteroidLvl1());
		this.currentLevel++;
		this.decreaseSpawnTime();
		
	}


	private void decreaseSpawnTime() {
		this.asteroidSpawnTime -= this.asteroidSpawnTime/10;
	}


	private void addAsteroids() {
		this.getCurrentSpawningAsteroids().clear();
		
		this.getCurrentSpawningAsteroids().add(this.getAsteroidLevel1());
		this.getCurrentSpawningAsteroids().add(this.getAsteroidLevel2());
		
		if (this.getCurrentLevel() > 3){
			this.getCurrentSpawningAsteroids().add(this.getAsteroidLevel2());
			this.getCurrentSpawningAsteroids().add(this.getAsteroidLevel3());
		}
		
		this.getScene().spawnAsteroids(this.getCurrentSpawningAsteroids());
	}


	private Asteroid getAsteroidLevel2() {
		AsteroidLvl2 ast = new AsteroidLvl2(100, 0);
		this.randomDir(ast);
		ast.setSpeed(this.randomSpeed());
		ast.setFragmentsSpeed(this.randomSpeed());
		return ast;
	}

	private Asteroid getAsteroidLevel3(){
		Asteroid ast = new AsteroidLvl3(200, 0);
		this.randomDir(ast);
		ast.setSpeed(this.randomSpeed());
		ast.setFragmentsSpeed(this.randomSpeed());
		return ast;
	}

	private double randomSpeed() {
		return Math.random()*35 + this.getCurrentLevel()*3;
	}
	private Asteroid getAsteroidLevel1() {
		Asteroid ast = new AsteroidLvl1(100, 0);
		this.randomDir(ast);
		ast.setSpeed(this.randomSpeed());
		return ast;
	}

	private Asteroid randomDir(Asteroid ast){
		ast.setDirVectX(1 + Math.random() + Math.random());
		
		if (Math.random() > 0.5){
			ast.setDirVectY(-1 + Math.random());
		}
		else{
			ast.setDirVectY(1 + Math.random());
		}
		return ast;
	}
	

	public List<Asteroid> getCurrentSpawningAsteroids() {
		return currentSpawningAsteroids;
	}


	public void setCurrentSpawningAsteroids(List<Asteroid> currentSpawningAsteroids) {
		this.currentSpawningAsteroids = currentSpawningAsteroids;
	}


	public void increaseAsteroidCounter(double time){
		this.asteroidTimeCounter += time;
	}
	public void increaseLevelTime(double time){
		this.levelTimeCounter += time;
	}
	public void resetLevelTimeCounter(){
		this.levelTimeCounter = 0;
	}
	public void resetAsteroidCounter(){
		this.asteroidTimeCounter = 0;
	}

	public MainGameScene getScene() {
		return scene;
	}


	public void setScene(MainGameScene scene) {
		this.scene = scene;
	}
}
